package com.jdk8.lambda;

import java.util.Arrays;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.jdk8.bean.Book;
/**https://segmentfault.com/a/1190000012302965
 * 所有的流操作会被组合到一个 stream pipeline(管道流），将多个简单操作连接在一起组成一个功能强大的操作。
 * 1、一个 stream pileline首先会有一个数据源，这个数据源可能是数组、集合、生成器函数或是IO通道，流操作过程中并不会修改源中的数据；
 * 2、然后还有零个或多个中间操作，每个中间操作会将接收到的流转换成另一个流（比如filter）；
 * 3、最后还有一个终止操作，会生成一个最终结果（比如sum）。
 * 流是一种惰性操作，所有对源数据的计算只在终止操作被初始化的时候才会执行。
 * 
 *流操作由3部分组成：
	1.源
	2.零个或多个中间操作
	3.终止操作 （到这一步才会执行整个stream pipeline计算）
 * 
 * 流的2中创建方法：
 *      1、通过Stream接口的of静态方法创建一个流
		    Stream<String> stream = Stream.of("hello", "world", "helloworld");
		2、通过Arrays类的stream方法，实际上第一种of方法底层也是调用的Arrays.stream(values);
			String[] array = new String[]{"hello","world","helloworld"};
		    Stream<String> stream3 = Arrays.stream(array);
		3、通过集合的stream方法，该方法是Collection接口的默认方法，所有集合都继承了该方法
		    Stream<String> stream2 = Arrays.asList("hello","world","helloworld").stream();
		 
		map方法是将一个容器里的元素映射到另一个容器中。
		flatMap方法，可以将多个容器的元素全部映射到一个容器中，即为扁平的map。
		list.stream().map(s -> s.toUpperCase()).collect(Collectors.toCollection(TreeSet::new));
		
 *
 */
public class StreamTest {

	public static void main(String[] args) {
//		List<Book> bklist = new ArrayList<>();
//		bklist.add(new Book("日历的由来", "jims", Arrays.asList(new String[] { "日历", "中国", "古代" })));
//		bklist.add(new Book("世界商业时代", "Hello", Arrays.asList(new String[] { "世界", "历史", "时代" })));
//		bklist.add(new Book("21世纪战争形态", "world", Arrays.asList(new String[] { "21世纪", "战争", "政治" })));
//		bklist.add(new Book("世界商业时代", "Hello", Arrays.asList(new String[] { "思维", "冲突", "合作" })));
//		String value = "世界商业时代";
		// Optional<Book> option=findFistObject(value,bklist);
		// Book bk=option.get();
		// System.out.println(bk.toString());

		// List<Book> bkList= findAllObject(value, bklist);
		// System.out.println("bklist.size="+bkList==null?0:bkList.size());

		//Map<String, List<Book>> map = groupListByAuthor(value, bklist);
		//System.out.println("map==" + JSON.toJSONString(getDistinceTags(bklist), true));
		
//		List<String> list = Arrays.asList("hello", "world", "helloworld");
//		List<String> upperList=list.stream().map(s -> s.toUpperCase()).collect(Collectors.toCollection(ArrayList::new));
//		upperList.forEach(System.out::println);
		
		Stream<List<Integer>> intStream=Stream.of(Arrays.asList(1,3,5),Arrays.asList(10,21,32,9,20,98));
//		List<Integer> intList=intStream.flatMap(s -> s.stream()).map(s ->s*2).collect(Collectors.toList());
//		intList.forEach(System.out::println);
		
		IntSummaryStatistics summary=intStream.flatMap(s -> s.stream()).filter(s ->s>3).mapToInt(s -> s).skip(2).limit(4).summaryStatistics();
		double avg=summary.getAverage();
		System.out.println("avg="+avg);
		System.out.println("max="+summary.getMax());
		
		//Stream.generate接收一个Supplier，适合生成连续不断的流或者一个全部是随机数的流
		//Stream.generate(Math::random).limit(10).distinct().findFirst().ifPresent(System.out::println);
		
		//特别要注意limit(long limit)l来限制结果集,否则会不断生成数据
		//Stream.iterate(11, s -> s+2).limit(5).forEach(System.out::println);;
	    
		List<String> festivalList=Stream.of(new String[] {"清明","重阳","中秋","国庆","端午","国庆"}).distinct().collect(Collectors.toList());
		festivalList.forEach(System.out::println);
	}

	// 匹配第一个
	public static Optional<Book> findFistObject(String value, List<Book> bklist) {
		return bklist.stream().filter(book -> book.getTitle().equals(value)).findFirst();
	}

	// 匹配所有的
	public static List<Book> findAllObject(String value, List<Book> bklist) {
		return bklist.stream().filter(book -> book.getTitle().equals(value)).collect(Collectors.toList());
	}

	// 分组查询
	public static Map<String, List<Book>> groupListByAuthor(String value, List<Book> bklist) {
		return bklist.stream().collect(Collectors.groupingBy(Book::getAuthor));
	}

	// 获取集合去重
	public static Set<String> getDistinceTags(List<Book> bklist) {
		return bklist.stream().flatMap(book -> book.getTags().stream()).collect(Collectors.toSet());
	}

}
